﻿using Microsoft.Extensions.Logging;
using RotovapPlatform.Domain.Business.Interfaces;
using RotovapPlatform.Domain.Business.Recipes.Entities;
using RotovapPlatform.Domain.Business.Recipes.Entities.Parameters;
using RotovapPlatform.Domain.Recipes.Services;
using static RotovapPlatform.Domain.Business.Recipe.Enums.RecipeEnums;

namespace RotovapPlatform.Application.Services;

/// <summary>
/// 配方应用服务实现
/// </summary>
public class RecipeAppService : IRecipeAppService
{
	private readonly IRecipeRepository _recipeRepository;
	private readonly IExperimentGroupRepository _experimentGroupRepository;
	private readonly IRecipeDomainService _domainService;
	private readonly ILogger<RecipeAppService> _logger;

	public RecipeAppService(
		IRecipeRepository recipeRepository,
		IExperimentGroupRepository experimentGroupRepository,
		IRecipeDomainService domainService,
		ILogger<RecipeAppService> logger)
	{
		_recipeRepository = recipeRepository;
		_experimentGroupRepository = experimentGroupRepository;
		_domainService = domainService;
		_logger = logger;
	}

	public async Task<IEnumerable<RecipeDefinition>> GetAllRecipesAsync()
	{
		try
		{
			return await _recipeRepository.GetAllAsync();
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "获取配方列表失败");
			return Enumerable.Empty<RecipeDefinition>();
		}
	}

	public async Task<(bool Success, string Message, Guid? RecipeId)> CreateRecipeAsync(RecipeDefinition recipe)
	{
		try
		{
			// 验证配方
			var (isValid, errorMessage) = await ValidateRecipeAsync(recipe);
			if (!isValid)
				return (false, errorMessage, null);

			// 记录当前状态
			_logger.LogDebug($"准备保存配方到数据库，ExperimentName: {recipe.ExperimentName}");

			await _recipeRepository.AddAsync(recipe);

			_logger.LogInformation($"配方 {recipe.ExperimentName} 保存成功");
			return (true, "创建成功", recipe.RecipeId);
		}
		catch (Exception ex)
		{
			_logger.LogError($"保存配方时发生错误: {ex.Message}");
			return (false, $"创建配方时发生错误: {ex.Message}", null);
		}
	}

	public async Task<(bool IsValid, string ErrorMessage)> ValidateRecipeAsync(RecipeDefinition recipe)
	{
		try
		{
			// 基本验证
			if (recipe == null)
				return (false, "配方数据不能为空");

			// 使用领域服务进行全面验证
			return await _domainService.ValidateRecipeAsync(recipe);
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "验证配方时发生错误");
			return (false, $"验证配方时发生错误: {ex.Message}");
		}
	}

	public async Task<(bool IsValid, string ErrorMessage)> ValidateParameterRangesAsync(RecipeDefinition recipe)
	{
		try
		{
			if (recipe?.RotovapParameters == null)
				return (false, "旋蒸参数不能为空");

			// 验证产物参数
			if (recipe.RotovapParameters.ProductParameters == null ||
				recipe.RotovapParameters.ProductParameters.Count == 0)
				return (false, "请至少添加一组产物参数");

			// 使用领域服务验证产物参数
			return await _domainService.ValidateProductParametersAsync(recipe.RotovapParameters.ProductParameters);
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "验证参数范围时发生错误");
			return (false, $"验证参数范围时发生错误: {ex.Message}");
		}
	}

	public async Task<(bool IsValid, string ErrorMessage)> ValidateMaterialsExistenceAsync(RecipeDefinition recipe)
	{
		try
		{
			if (recipe?.RotovapParameters == null)
				return (false, "旋蒸参数不能为空");

			// 使用领域服务验证物料和清洗液是否存在
			return await _domainService.ValidateMaterialsExistenceAsync(recipe);
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "验证物料存在性时发生错误");
			return (false, $"验证物料存在性时发生错误: {ex.Message}");
		}
	}

	public async Task<(bool Success, string Message)> UpdateRecipeAsync(RecipeDefinition recipe)
	{
		try
		{
			// 使用完整的验证逻辑
			var (isValid, errorMessage) = await ValidateRecipeAsync(recipe);
			if (!isValid)
				return (false, errorMessage);

			await _recipeRepository.UpdateAsync(recipe);
			return (true, "更新成功");
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "更新配方失败");
			return (false, "更新配方时发生错误");
		}
	}

	public async Task<RecipeDefinition> GetRecipeByIdAsync(Guid recipeId)
	{
		return await _recipeRepository.GetByIdAsync(recipeId);
	}

	public async Task<(bool Success, string Message)> DeleteRecipeAsync(Guid recipeId)
	{
		try
		{
			await _recipeRepository.DeleteAsync(recipeId);
			return (true, "删除成功");
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "删除配方失败");
			return (false, "删除配方时发生错误");
		}
	}

	public async Task<(bool Success, string Message, Guid? RecipeId)> CloneRecipeAsync(
		Guid sourceRecipeId)
	{
		try
		{
			var sourceRecipe = await _recipeRepository.GetByIdAsync(sourceRecipeId);
			if (sourceRecipe == null)
				return (false, "源配方不存在", null);

			// 创建新配方
			var newRecipe = new RecipeDefinition
			{
				RecipeId = Guid.NewGuid(),
				ExperimentName = $"{sourceRecipe.ExperimentName}_副本",
				ExperimentDescription = sourceRecipe.ExperimentDescription,
				ExperimentType = sourceRecipe.ExperimentType,
				Operator = sourceRecipe.Operator,
				CreatedTime = DateTime.Now,
				RotovapParameters = sourceRecipe.RotovapParameters // 假设 RotovapParameters 已经实现了深拷贝
			};

			await _recipeRepository.AddAsync(newRecipe);
			return (true, "复制成功", newRecipe.RecipeId);
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "复制配方失败");
			return (false, "复制配方时发生错误", null);
		}
	}

	public async Task<IEnumerable<ExperimentGroup>> GetAllExperimentGroupsAsync()
	{
		try
		{
			return await _experimentGroupRepository.GetAllAsync();
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "获取实验组列表失败");
			return Enumerable.Empty<ExperimentGroup>();
		}
	}

	public async Task<(bool Success, string Message, Guid? GroupId)> CreateExperimentGroupAsync(ExperimentGroup group)
	{
		try
		{
			if (await _experimentGroupRepository.ExistsByNameAsync(group.GroupName))
			{
				return (false, "实验组名称已存在", null);
			}

			group.GroupId = Guid.NewGuid();
			group.CreatedTime = DateTime.Now;

			// 确保所有配方都已经被正确保存到数据库中
			if (group.Recipes != null && group.Recipes.Count > 0)
			{
				var recipes = new List<RecipeDefinition>();
				foreach (var recipe in group.Recipes)
				{
					// 从数据库中获取配方，确保它存在
					var dbRecipe = await _recipeRepository.GetByIdAsync(recipe.RecipeId);
					if (dbRecipe == null)
					{
						// 如果配方不存在，尝试保存它
						await _recipeRepository.AddAsync(recipe);
						dbRecipe = recipe;
					}

					// 检查配方的RotovapParameters是否为null（仅用于调试）
					_logger.LogDebug($"配方 {dbRecipe.ExperimentName} 的RotovapParameters: {(dbRecipe.RotovapParameters == null ? "null" : "有值")}");

					recipes.Add(dbRecipe);
				}

				// 使用从数据库中获取的配方替换原有的配方集合
				group.Recipes.Clear();
				foreach (var recipe in recipes)
				{
					group.Recipes.Add(recipe);
				}
			}

			// 注意：不再自动创建实验，只有在准备执行时才会创建
			// group.CreateExperimentsFromRecipes();
			_logger.LogInformation($"创建实验组 {group.GroupName}，包含 {group.Recipes?.Count ?? 0} 个配方，暂不创建实验数据");

			// 添加实验组，不创建实验数据
			await _experimentGroupRepository.AddAsync(group, updateExperiments: false);
			return (true, "创建成功", group.GroupId);
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "创建实验组失败");
			return (false, "创建实验组时发生错误", null);
		}
	}

	public async Task<(bool Success, string Message)> UpdateExperimentGroupAsync(ExperimentGroup group)
	{
		try
		{
			var existingGroup = await _experimentGroupRepository.GetByIdAsync(group.GroupId);
			if (existingGroup == null)
			{
				return (false, "实验组不存在");
			}

			// 更新实验组，默认不更新实验数据
			await _experimentGroupRepository.UpdateAsync(group, false);
			_logger.LogInformation($"更新实验组 {group.GroupId}，不更新实验数据");

			return (true, "更新成功");
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "更新实验组失败");
			return (false, "更新实验组时发生错误");
		}
	}

	public async Task<(bool Success, string Message)> DeleteExperimentGroupAsync(Guid groupId)
	{
		try
		{
			await _experimentGroupRepository.DeleteAsync(groupId);
			return (true, "删除成功");
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "删除实验组失败");
			return (false, "删除实验组时发生错误");
		}
	}

	public async Task<(bool Success, string Message, ExperimentGroup Group)> GetExperimentGroupByNameAsync(string groupName)
	{
		try
		{
			var group = await _experimentGroupRepository.GetByNameAsync(groupName);
			if (group == null)
			{
				return (false, "实验组不存在", null);
			}
			return (true, "获取成功", group);
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "获取实验组失败");
			return (false, "获取实验组时发生错误", null);
		}
	}

	/// <summary>
	/// 添加配方到实验组
	/// </summary>
	public async Task<(bool Success, string Message)> AddRecipeToGroupAsync(Guid groupId, Guid recipeId)
	{
		try
		{
			// 获取实验组
			var group = await _experimentGroupRepository.GetByIdAsync(groupId);
			if (group == null)
			{
				return (false, "实验组不存在");
			}

			// 获取要添加的配方
			var recipe = await _recipeRepository.GetByIdAsync(recipeId);
			if (recipe == null)
			{
				return (false, "配方不存在");
			}

			// 检查配方是否已在实验组中
			if (group.Recipes.Any(r => r.RecipeId == recipeId))
			{
				return (false, "该配方已在实验组中");
			}

			// 添加配方到实验组（只添加引用，不添加整个对象）
			// 创建一个简化的配方对象，只包含必要的信息
			var recipeReference = new RecipeDefinition
			{
				RecipeId = recipe.RecipeId,
				ExperimentName = recipe.ExperimentName,
				ExperimentDescription = recipe.ExperimentDescription,
				ExperimentType = recipe.ExperimentType,
				CreatedTime = recipe.CreatedTime,
				Operator = recipe.Operator,
				RotovapParameters = recipe.RotovapParameters?.Clone() ?? new RotovapParameters()
			};

			// 添加调试日志
			_logger.LogDebug($"添加配方到实验组: recipeId={recipeId}, groupId={groupId}");
			_logger.LogDebug($"配方参数: RotovapParameters={recipeReference.RotovapParameters != null}");

			// 重新获取最新的实验组数据，避免并发问题
			var freshGroup = await _experimentGroupRepository.GetByIdAsync(groupId);
			if (freshGroup == null)
			{
				return (false, "实验组不存在或已被删除");
			}

			// 将新配方添加到最新的实验组数据中
			freshGroup.Recipes.Add(recipeReference);

			// 注意：此处不再创建实验数据，只有在执行时才会创建
			_logger.LogInformation($"配方 {recipeId} 已添加到实验组 {groupId}，但尚未创建实验数据");

			// 更新实验组，显式指定不更新实验数据
			await _experimentGroupRepository.UpdateAsync(freshGroup, updateExperiments: false);

			return (true, "添加成功");
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "添加配方到实验组失败");
			return (false, $"添加配方到实验组时发生错误: {ex.Message}");
		}
	}

	public async Task<(bool Success, string Message)> GetRecipesByGroupAsync(Guid groupId)
	{
		try
		{
			var recipes = await _experimentGroupRepository.GetByIdAsync(groupId);
			return (true, "获取配方成功");
		}
		catch (Exception ex)
		{
			_logger.LogError(ex, "获取配方失败");
			return (false, "获取配方失败");
		}
	}


}